import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:mi_mang_flutter/manager/app_manager.dart';
import 'routers.dart';

/// fluro的路由跳转工具类

class NavigatorUtils {
  /// [path] 跳转地址
  ///
  /// [replace] 是否替换当前页
  ///
  /// [clearStack] 是否清空堆栈中的其他页
  ///
  /// [transition] 跳转方式,如:从下往上打开,弹出模态窗口等.默认(native)
  ///
  /// 注意 transition的值设置为custom,需要另外处理,目前未作兼容处理
  static push(
    BuildContext context,
    String path, {
    bool replace = false,
    bool clearStack = false,
    Duration transitionDuration = const Duration(milliseconds: 250),
    TransitionType transition = TransitionType.native,
  }) {
    unfocus();
    AppManager.router!.navigateTo(
      context,
      path,
      replace: replace,
      clearStack: clearStack,
      transitionDuration: transitionDuration,
      transition: transition,
    );
  }

  /// [path] 跳转地址
  ///
  /// [function] 跳转后的值回调函数
  /// 如: 跳转 NavigatorUtils.pushResult(context, path, (result) { });
  ///
  /// result 为上一页页返回的结果
  ///
  /// [注意] 需要调用对应的返回方法:
  ///
  /// NavigatorUtils.goBackWithParams(context, result)
  ///
  /// [replace] 是否替换当前页
  ///
  /// [clearStack] 是否清空堆栈中的其他页
  ///
  /// [transition] 跳转方式,如:从下往上打开,弹出模态窗口等.默认(native)
  ///
  /// 注意 transition的值设置为custom,需要另外处理,目前未作兼容处理
  static pushResult(
    BuildContext context,
    String path,
    Function(Object) function, {
    bool replace = false,
    bool clearStack = false,
    TransitionType transition = TransitionType.native,
  }) {
    unfocus();
    AppManager.router!
        .navigateTo(
      context,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: transition,
    )
        .then((result) {
      // 页面返回result为null
      if (result == null) {
        return;
      }
      function(result);
    }).catchError((error) {
      print("$error");
    });
  }

  /// 返回
  static void goBack(BuildContext context) {
    unfocus();
    var canPop = ModalRoute.of(context)!.navigator!.canPop();
    if (canPop) {
      Navigator.pop(context);
    }
  }

  /// 带参数返回
  static void goBackWithParams<T extends Object>(
      BuildContext context, T result) {
    unfocus();
    var canPop = ModalRoute.of(context)!.navigator!.canPop();
    if (canPop) {
      Navigator.pop<T>(context, result);
    }
  }

  /// 跳到WebView页
  static void goWebViewPage(BuildContext context, String title, String url) {
    unfocus();
    //fluro 不支持传中文,需转换
    push(
      context,
      '${Routes.webViewPage}?title=${Uri.encodeComponent(title)}&url=${Uri.encodeComponent(url)}',
    );
  }

  /// 回退至predicatePaths的其中一个
  /// 由于可能跳转的入口不一致,导致路由堆栈中不一定有指定的路由,所以该处改为数组
  ///
  /// ```dart
  /// void _logout() {
  ///   NavigatorUtils.goBackUntil(context, [OrderRoute.OrderTab]);
  /// }
  /// ```
  /// popUntil, 弹出路由, 直到predicate返回true
  static void goBackUntil(BuildContext context,
      {List<String>? predicatePaths}) {
    unfocus();
    Navigator.popUntil(context, (Route<dynamic> route) {
      // 由于携带参数时,无法使用ModalRoute.withName方法进行判断是否返回true,所以该处自定义写法
      // 为防止跳转后无法点击返回按钮,默认最底层为Routes.main
      var predicate = (predicatePaths != null &&
              predicatePaths.contains(route.settings.name!.split("?").first)) ||
          route.settings.name!.split("?").first == Routes.main;
      return !route.willHandlePopInternally && route is ModalRoute && predicate;
    });
  }

  /// 跳转页面并弹出之前的路由
  /// [path] 跳转的路由
  ///
  /// [predicatePaths] 退回的路由组,默认包含主界面(Routes.main),防止跳转后无法点击返回按钮,两者之间的路由全部都会被销毁;
  /// 由于可能跳转的入口不一致,导致路由堆栈中不一定有指定的路由,所以该处改为数组
  ///
  /// ```dart 如下: 跳转到支付页,并关闭订单tab列表之前的所有页面
  ///   Navigator.pushAndGoBackUntil(
  ///     context,
  ///     OrderRoute.OrderSucess,
  ///     [OrderRoute.OrderTab],
  ///   );
  /// ```
  static Future<T?> pushAndGoBackUntil<T extends Object>(
    BuildContext context,
    String path,
    List<String> predicatePaths, {
    TransitionType transition = TransitionType.native,
  }) {
    unfocus();
    // 添加transitionType参数,可以控制页面打开方式(左侧打开,底部弹出等))
    RouteMatch match = AppManager.router!.matchRoute(
      context,
      path,
      transitionType: transition,
    );
    // 由于携带参数时,无法使用ModalRoute.withName方法进行判断是否返回true,所以该处自定义写法
    RoutePredicate predicate = (Route<dynamic> route) {
      return !route.willHandlePopInternally &&
          route is ModalRoute &&
          route.settings.name != null &&
          (predicatePaths.contains(route.settings.name!.split("?").first) ||
              route.settings.name!.split("?").first == Routes.main);
    };
    return Navigator.pushAndRemoveUntil<T?>(
        context, match.route as Route<T?>, predicate);
  }

  static void unfocus() {
    // 使用下面的方式，会触发不必要的build。
    // FocusScope.of(context).unfocus();
    // https://github.com/flutter/flutter/issues/47128#issuecomment-627551073
    FocusManager.instance.primaryFocus?.unfocus();
  }
}
